package com.xz.coursearrange.common.exceptions;

import com.xz.coursearrange.common.ServerResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Descripe: 统一异常处理
 */

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {


    // 对所有的异常进行相同的处理
    @ExceptionHandler(AbstractCourseArrangeException.class)
    public ServerResponse error(Exception e) {
        log.error(e.getMessage());
        return ServerResponse.ofError("服务器出现异常");
    }


    // JSON 请求体校验失败
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ServerResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        for (FieldError error : ex.getBindingResult().getFieldErrors()) {
            errors.put(error.getField(), error.getDefaultMessage());
            return ServerResponse.ofError(String.format("参数校验失败: %s", error.getDefaultMessage()), errors);
        }
        return ServerResponse.ofError("参数校验失败", errors);
    }

    // 表单参数（如 @Validated @RequestParam）绑定失败
    @ExceptionHandler(BindException.class)
    public ServerResponse handleBindException(BindException ex) {
        Map<String, String> errors = new HashMap<>();
        for (FieldError error : ex.getBindingResult().getFieldErrors()) {
            errors.put(error.getField(), error.getDefaultMessage());
            return ServerResponse.ofError(String.format("参数绑定失败: %s", error.getDefaultMessage()), errors);
        }
        return ServerResponse.ofError("参数绑定失败", errors);
    }

    // 单个参数校验失败
    @ExceptionHandler(ConstraintViolationException.class)
    public ServerResponse handleConstraintViolationException(ConstraintViolationException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getConstraintViolations().forEach(violation -> {
                    errors.put(violation.getPropertyPath().toString(), violation.getMessage());
                }
        );
        return ServerResponse.ofError(String.format("路径参数校验失败: %s",   ex.getConstraintViolations().iterator().next().getMessage()), errors);
    }


}
